package com.github.itdachen.utils;

import com.github.itdachen.constants.JavaFieldConstants;
import com.github.itdachen.constants.UiStyleConstant;
import com.github.itdachen.framework.core.utils.StringUtils;
import com.github.itdachen.sdk.vo.DevTableColumnVO;
import com.github.itdachen.sdk.vo.DevTableInfoVO;
import org.apache.velocity.VelocityContext;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;

/**
 * 代码生成模版参数设置
 *
 * @author 王大宸
 * @date 2024/4/3 22:11
 */
public class VelocityContextUtils {
    private static final Snowflake snowflake = new Snowflake(1, 1, 0L);

    /**
     * 默认上级菜单，系统工具
     */
    private static final String DEFAULT_PARENT_MENU_ID = "1539506077102641152";

    /***
     * 设置模板变量信息
     *
     * @author 王大宸
     * @date 2024/4/15 23:54
     * @param tableInfo tableInfo
     * @return org.apache.velocity.VelocityContext
     */
    public static VelocityContext prepareContext(DevTableInfoVO tableInfo) {
        String packageName = tableInfo.getRearPackage() + "." + tableInfo.getModuleName();
        String functionName = tableInfo.getFuncName();

        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put("appId", StringUtils.isEmpty(tableInfo.getAppId()) ? "admin" : tableInfo.getAppId());
        velocityContext.put("iframe", StringUtils.isEmpty(tableInfo.getIframe()) ? "_component" : tableInfo.getIframe());
        velocityContext.put("tplCategory", tableInfo.getRearTemp());
        velocityContext.put("tableName", tableInfo.getTableName());
        velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "【请填写功能名称】");
        velocityContext.put("askUri", tableInfo.getAskUri());
        velocityContext.put("rearUri", tableInfo.getRearUri());

        velocityContext.put("frontPackage", tableInfo.getFrontPackage());

        velocityContext.put("moduleName", tableInfo.getModuleName());
        velocityContext.put("basePackage", getPackagePrefix(packageName));
        velocityContext.put("packageName", packageName);
        velocityContext.put("datetime", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));
        velocityContext.put("pkColumn", tableInfo.getPkColumn());
        velocityContext.put("importList", getImportList(tableInfo));

        velocityContext.put("table", tableInfo);
        velocityContext.put("package", setPackage(tableInfo));
        velocityContext.put("contextPath", contextPathHandler(tableInfo.getContextPath()));
        velocityContext.put("author", tableInfo.getFuncAuthor() == null || "".equals(tableInfo.getFuncAuthor()) ? "<请填写作者名称>" : tableInfo.getFuncAuthor());
        velocityContext.put("comments", tableInfo.getColumns());
        velocityContext.put("functionName", tableInfo.getFuncName());
        velocityContext.put("ClassName", tableInfo.getClazzName());
        velocityContext.put("className", StringUtils.uncapitalize(tableInfo.getClazzName()));
        velocityContext.put("upperClassName", tableInfo.getClazzName().replaceAll("([a-z])([A-Z])", "$1_$2").toUpperCase());
        velocityContext.put("primaryKey", tableInfo.getPkColumn().getJavaType());
        velocityContext.put("pkColumn", tableInfo.getPkColumn());
        velocityContext.put("permsPrefix", permsPrefix(tableInfo));
        velocityContext.put("pathPrefix", tableInfo.getFrontPackage());

        /* 实体类字段 */
        velocityContext.put("columns", tableInfo.getColumns());
        velocityContext.put("queryColumns", queryColumnName(tableInfo.getColumns()));
        velocityContext.put("dtoColumns", dtoColumnName(tableInfo.getColumns()));
        velocityContext.put("voColumns", voColumnName(tableInfo.getColumns()));
        velocityContext.put("expColumns", expColumnName(tableInfo.getColumns()));

        /* 菜单 */
        velocityContext.put("pMenuId", tableInfo.getMenuId() == null || "".equals(tableInfo.getMenuId()) ? DEFAULT_PARENT_MENU_ID : tableInfo.getMenuId());
        velocityContext.put("appId", tableInfo.getAppId());
        velocityContext.put("menuId", getId());
        velocityContext.put("pageId", getId());
        velocityContext.put("addId", getId());
        velocityContext.put("editId", getId());
        velocityContext.put("seeId", getId());
        velocityContext.put("delId", getId());
        velocityContext.put("expId", getId());

        /* 序力化 */
        velocityContext.put("entityMostSigBits", getMostSigBits());
        velocityContext.put("dtoMostSigBits", getMostSigBits());
        velocityContext.put("voMostSigBits", getMostSigBits());
        velocityContext.put("queryMostSigBits", getMostSigBits());

        velocityContext.put("menuDate", getNowTime());


        /* 菜单表名 ta_fly_route */
        String routeTablePrefix = "ta_fly_route";
        if (UiStyleConstant.VUE_LAY_UI.equals(tableInfo.getFrontUiStyle())) {
            routeTablePrefix = "fly_next_resource";
        }
        velocityContext.put("routeTablePrefix", routeTablePrefix);


        return velocityContext;
    }


    public static String getId() {
        return String.valueOf(snowflake.nextId());
    }

    public static String getMostSigBits() {
        return String.valueOf(snowflake.getMostSigBits());
    }


    public static String getNowTime() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return LocalDateTime.now().format(dateTimeFormatter);
    }


    /**
     * 获取包前缀
     *
     * @param packageName 包名称
     * @return 包前缀名称
     */
    private static String getPackagePrefix(String packageName) {
        int lastIndex = packageName.lastIndexOf(".");
        return StringUtils.substring(packageName, 0, lastIndex);
    }


    /***
     * 获取 查询/query 属性的字段
     *
     * @author 王大宸
     * @date 2023/4/11 21:29
     * @param columns columns
     * @return java.util.List<com.github.itdachen.framework.code.sdk.vo.TableColumnVo>
     */
    private static List<DevTableColumnVO> queryColumnName(List<DevTableColumnVO> columns) {
        List<DevTableColumnVO> list = new ArrayList<>();
        for (DevTableColumnVO column : columns) {
            if (GenConstants.REQUIRE.equals(column.getIsQuery())) {
                list.add(column);
            }
        }
        return list;
    }


    /***
     * 获取 dto/vo 属性的字段
     *
     * @author 王大宸
     * @date 2023/4/11 21:15
     * @param columns columns
     * @return java.util.List<com.github.itdachen.framework.code.sdk.vo.TableColumnVo>
     */
    private static List<DevTableColumnVO> dtoColumnName(List<DevTableColumnVO> columns) {
        List<DevTableColumnVO> list = new ArrayList<>();
        for (DevTableColumnVO column : columns) {
            if (GenConstants.REQUIRE.equals(column.getIsDto())) {
                list.add(column);
            }
        }
        return list;
    }

    private static List<DevTableColumnVO> voColumnName(List<DevTableColumnVO> columns) {
        List<DevTableColumnVO> list = new ArrayList<>();
        for (DevTableColumnVO column : columns) {
            if (GenConstants.REQUIRE.equals(column.getIsVo())) {
                list.add(column);
            }
        }
        return list;
    }

    private static List<DevTableColumnVO> expColumnName(List<DevTableColumnVO> columns) {
        List<DevTableColumnVO> list = new ArrayList<>();
        for (DevTableColumnVO column : columns) {
            if (GenConstants.REQUIRE.equals(column.getIsExp())) {
                list.add(column);
            }
        }
        return list;
    }

    /***
     * 根据列类型获取导入包
     *
     * @author 王大宸
     * @date 2025/3/11 22:28
     * @param genTable 业务表对象
     * @return java.util.HashSet<java.lang.String>  返回需要导入的包列表
     */
    private static HashSet<String> getImportList(DevTableInfoVO genTable) {
        List<DevTableColumnVO> columns = genTable.getColumns();
        HashSet<String> importList = new HashSet<String>();
        for (DevTableColumnVO column : columns) {
            if (column.isSuperColumn()) {
                continue;
            }
            if (JavaFieldConstants.LOCAL_DATE_TIME.equals(column.getJavaType())) {
                importList.add("java.time.LocalDateTime");
                continue;
            }
            if (JavaFieldConstants.BIG_DECIMAL.equals(column.getJavaType())) {
                importList.add("java.math.BigDecimal");
            }
        }
        return importList;
    }

    private static String contextPathHandler(String contextPath) {
        if (null == contextPath || "".equals(contextPath)) {
            return "";
        }
        if (contextPath.startsWith("/")) {
            return contextPath;
        }
        return "/" + contextPath;
    }

    /***
     * 权限标识前缀
     *
     * @author 王大宸
     * @date 2022/8/1 16:38
     * @param tableInfo tableInfo
     * @return java.lang.String
     */
    private static String permsPrefix(DevTableInfoVO tableInfo) {
        String askUri = tableInfo.getAskUri();
        String permsPrefix = askUri.replaceAll("//", "/").replaceAll("/", ":").replaceAll("::", ":");
        if (permsPrefix.startsWith(":")) {
            permsPrefix = permsPrefix.substring(1);
        }
        return permsPrefix;


//        String permsPrefix = "";
//        if (tableInfo.getModuleName().equals(tableInfo.getRearUri())) {
//            tableInfo.setModuleName(null);
//        }
//        if (StringUtils.isNotEmpty(tableInfo.getContextPath()) && !"/".equals(tableInfo.getContextPath()) && !":".equals(tableInfo.getContextPath())) {
//            permsPrefix = tableInfo.getContextPath().replaceAll("/", "") + ":";
//        }
//        if (StringUtils.isNotEmpty(tableInfo.getRearUri()) && !"/".equals(tableInfo.getRearUri()) && !":".equals(tableInfo.getRearUri())) {
//            permsPrefix += trimStr(tableInfo.getRearUri()) + ":";
//        }
//        if (StringUtils.isNotEmpty(tableInfo.getModuleName()) && !"/".equals(tableInfo.getModuleName()) && !":".equals(tableInfo.getModuleName())) {
//            if (!permsPrefix.startsWith(tableInfo.getModuleName())) {
//                permsPrefix = permsPrefix + trimStr(tableInfo.getModuleName());
//            }
//        }
//        permsPrefix = permsPrefix.toLowerCase()
//                .replaceAll("/", ":")
//                .replaceAll("::", ":")
//                .replaceAll(" ", "");
//        return permsPrefix;


//        String permsPrefix = "" ;
//        if (tableInfo.getModuleName().equals(tableInfo.getRearUri())) {
//            tableInfo.setModuleName(null);
//        }
//        if (StringUtils.isNotEmpty(tableInfo.getRearUri()) && !"/".equals(tableInfo.getRearUri()) && !":".equals(tableInfo.getRearUri())) {
//            permsPrefix += trimStr(tableInfo.getRearUri());
//        }
//        if (permsPrefix.startsWith(":")) {
//            permsPrefix = permsPrefix.substring(1);
//        }
//        if (StringUtils.isNotEmpty(tableInfo.getModuleName()) && !"/".equals(tableInfo.getModuleName()) && !":".equals(tableInfo.getModuleName())) {
//            if (!permsPrefix.startsWith(tableInfo.getModuleName())) {
//                permsPrefix = trimStr(tableInfo.getModuleName()) + ":" + permsPrefix;
//            }
//        }
//        permsPrefix = permsPrefix.toLowerCase()
//                .replaceAll("/", ":")
//                .replaceAll("::", ":")
//                .replaceAll(" ", "");
//        return permsPrefix;
    }

    private static String trimStr(String str) {
        return str.replaceAll("/", ":").replaceAll("\"", "").replaceAll(" ", "").trim();
    }


    /***
     * 包路径设置
     *
     * @author 王大宸
     * @date 2024/4/16 0:21
     * @param tableInfo tableInfo
     * @return java.lang.String
     */
    private static String setPackage(DevTableInfoVO tableInfo) {
        String rearPackage = tableInfo.getRearPackage();
        String moduleName = tableInfo.getModuleName();

        if (null == moduleName || moduleName.isEmpty() || rearPackage.endsWith(moduleName)) {
            return rearPackage;
        }
        moduleName = moduleName.replaceAll("/", ".");
        if (rearPackage.endsWith(moduleName)) {
            return rearPackage;
        }
        return rearPackage + "." + moduleName;
    }


}
